/*****************************************************************************
*                                                                            *
*  OpenNI 1.x Alpha                                                          *
*  Copyright (C) 2012 PrimeSense Ltd.                                        *
*                                                                            *
*  This file is part of OpenNI.                                              *
*                                                                            *
*  Licensed under the Apache License, Version 2.0 (the "License");           *
*  you may not use this file except in compliance with the License.          *
*  You may obtain a copy of the License at                                   *
*                                                                            *
*      http://www.apache.org/licenses/LICENSE-2.0                            *
*                                                                            *
*  Unless required by applicable law or agreed to in writing, software       *
*  distributed under the License is distributed on an "AS IS" BASIS,         *
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
*  See the License for the specific language governing permissions and       *
*  limitations under the License.                                            *
*                                                                            *
*****************************************************************************/
package com.robb19y.rgbdscanner.calibration;

import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
import java.rmi.RemoteException;
import java.awt.*;
import java.awt.image.*;

import org.OpenNI.Context;
import org.OpenNI.DepthGenerator;
import org.OpenNI.DepthMetaData;
import org.OpenNI.GeneralException;
import org.OpenNI.ImageGenerator;
import org.OpenNI.ImageMetaData;
import org.OpenNI.NodeType;
import org.OpenNI.OutArg;
import org.OpenNI.ScriptNode;
import org.OpenNI.StatusException;

class SimpleViewer extends Component {

    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;	    
    private DepthGenerator depthGen;
    private byte[] imgbytes;
    private float histogram[];
    
	/*OpenNI attributes*/
	private static final String SAMPLES_XML = "config/SamplesConfig.xml";	
	private OutArg<ScriptNode> scriptNodeArg;
	private Context context;
	private DepthGenerator depthGenerator;
	private DepthMetaData depthMD;
	private ImageGenerator imageGenerator;
	private ImageMetaData imageMD;	
	private CalibrationToolGui ctg;

    private BufferedImage bimg;
    int width, height;
      
    public SimpleViewer(CalibrationToolGui ctg) {
    	this.ctg = ctg;
        try {
        	scriptNodeArg = new OutArg<ScriptNode>();
            context = Context.createFromXmlFile(SAMPLES_XML, scriptNodeArg);
            histogram = new float[10000];
            
            //Initialize context
    		scriptNodeArg = new OutArg<ScriptNode>();
    		context = Context.createFromXmlFile(SAMPLES_XML, scriptNodeArg);		
    		context.waitAnyUpdateAll();	
    		System.out.println("Context initialized.");		
    		
    		//Initialize RGB sensor
    		imageGenerator = (ImageGenerator) context.findExistingNode(NodeType.IMAGE);
    		imageMD = new ImageMetaData();		
    		imageGenerator.getMetaData(imageMD);
    		System.out.println("RGB sensor initialized. Resolution: "+imageMD.getXRes()+" x "+imageMD.getYRes()+".");
    		
    		//Initialize depth sensor
    		depthGenerator = (DepthGenerator)context.findExistingNode(NodeType.DEPTH);
    		depthGenerator.getAlternativeViewpointCapability().setViewpoint(imageGenerator);
    		depthMD = new DepthMetaData();
    		depthGenerator.getMetaData(depthMD);		
    		System.out.println("Depth sensor initialized. Resolution: "+depthMD.getXRes()+" x "+depthMD.getYRes()+".");
            
            width = depthMD.getFullXRes();
            height = depthMD.getFullYRes();
            
            imgbytes = new byte[width*height];
            
            DataBufferByte dataBuffer = new DataBufferByte(imgbytes, width*height);
            Raster raster = Raster.createPackedRaster(dataBuffer, width, height, 8, null);
            bimg = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
            bimg.setData(raster);

        } catch (GeneralException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
    
    private void calcHist(DepthMetaData depthMD)
    {
        // reset
        for (int i = 0; i < histogram.length; ++i)
            histogram[i] = 0;
        
        ShortBuffer depth = depthMD.getData().createShortBuffer();
        depth.rewind();

        int points = 0;
        while(depth.remaining() > 0)
        {
            short depthVal = depth.get();
            if (depthVal != 0)
            {
                histogram[depthVal]++;
                points++;
            }
        }
        
        for (int i = 1; i < histogram.length; i++)
        {
            histogram[i] += histogram[i-1];
        }

        if (points > 0)
        {
            for (int i = 1; i < histogram.length; i++)
            {
                histogram[i] = (int)(256 * (1.0f - (histogram[i] / (float)points)));
            }
        }
    }
    
	public void readRGBD() throws StatusException{	
		
		//Read sensor
		context.waitAnyUpdateAll();	
		depthGenerator.getMetaData(depthMD);
		imageGenerator.getMetaData(imageMD);
		calcHist(depthMD);
		
        /*ShortBuffer depth = depthMD.getData().createShortBuffer();
        depth.rewind();
        
        while(depth.remaining() > 0){
            int pos = depth.position();
            short pixel = depth.get();
            imgbytes[pos] = (byte)histogram[pixel];
        }*/		
		
		ByteBuffer imageBuffer = imageMD.getData().createByteBuffer();		
		
		int i=0,r=0,g=0,b=0;		
		//Data acquisition
		for (int x = 0; x < imageMD.getXRes(); x++) {
			for (int y = 0; y < imageMD.getYRes(); y++) {
				i = y * imageMD.getXRes() + x;
				//Get depth value					
				short z = depthMD.getData().readPixel(x, y);
				
				//Get RGB values						
				r = imageBuffer.get(i * 3)  & 0xff; 
				g = imageBuffer.get(i * 3 + 1)  & 0xff; 
				b = imageBuffer.get(i * 3 + 2)  & 0xff;
				
						
				if(ctg.getColorFilter().filter(new double[]{r,g,b}) && z > 0){
					imgbytes[i] = (byte)histogram[z];					
					//imgbytes[i] = (byte)250;
				}else{
					imgbytes[i] = (byte) 0;	
					
				}
			
			}			
		}
	}

    public Dimension getPreferredSize() {
        return new Dimension(width, height);
    }

    public void paint(Graphics g) {
        DataBufferByte dataBuffer = new DataBufferByte(imgbytes, width*height);
        Raster raster = Raster.createPackedRaster(dataBuffer, width, height, 8, null);
        bimg.setData(raster);

        g.drawImage(bimg, 0, 0, null);
    }
}

